package com.info.zhiduoduo.admin.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.Condition;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.constants.company.CompanyPayType;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceUserType;
import com.info.zhiduoduo.common.constants.pay.PayTypeSn;
import com.info.zhiduoduo.common.constants.project.ProjectType;
import com.info.zhiduoduo.common.exception.Asserts;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.utils.MD5Util;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.RandomUtil;
import com.info.zhiduoduo.common.utils.StringUtil;
import com.info.zhiduoduo.core.service.CoreBrokerageService;
import com.info.zhiduoduo.core.service.CoreInvoiceService;
import com.info.zhiduoduo.core.service.payment.thirdpay.ZhaoShangTradeBulterService;
import com.info.zhiduoduo.repository.dto.company.CompanyDetailDto;
import com.info.zhiduoduo.repository.dto.maker.MakerDetailDto;
import com.info.zhiduoduo.repository.entity.company.*;
import com.info.zhiduoduo.repository.entity.crowdsource.Crowdsource;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceAccount;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceInvoice;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceProject;
import com.info.zhiduoduo.repository.entity.crowdsource.CrowdsourceProjectItem;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProject;
import com.info.zhiduoduo.repository.entity.entrustmentproject.EntrustmentProjectItem;
import com.info.zhiduoduo.repository.entity.invoice.Invoice;
import com.info.zhiduoduo.repository.entity.maker.Maker;
import com.info.zhiduoduo.repository.entity.maker.MakerAlipayPrincipal;
import com.info.zhiduoduo.repository.entity.order.TradeRecord;
import com.info.zhiduoduo.repository.entity.partner.PartnerAccountflow;
import com.info.zhiduoduo.repository.entity.partner.PartnerBrokerage;
import com.info.zhiduoduo.repository.entity.pay.Payment;
import com.info.zhiduoduo.repository.mapper.company.CompanyMapper;
import com.info.zhiduoduo.repository.mapper.company.CompanyProjectMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceAccountMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceMapper;
import com.info.zhiduoduo.repository.mapper.invoice.InvoiceMapper;
import com.info.zhiduoduo.repository.mapper.maker.MakerMapper;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ZzFixService {

	@Autowired
	CoreInvoiceService coreInvoiceService;
	@Autowired
	CoreBrokerageService coreBrokerageService;
	@Autowired
	ZhaoShangTradeBulterService zhaoShangTradeBulterService;

	@Resource
	CrowdsourceMapper crowdsourceMapper;
	@Resource
	CrowdsourceAccountMapper crowdsourceAccountMapper;
	@Resource
	InvoiceMapper invoiceMapper;
	@Resource
	MakerMapper makerMapper;
	@Resource
	CompanyMapper companyMapper;
	@Resource
	CompanyProjectMapper companyProjectMapper;

	public void fixCrowdsourceFromImprotProject() {
		log.info("开始fixCrowdsourceFromImprotProject -----");
		List<Crowdsource> crowdsourceList = new Crowdsource().selectList(Condition.create().eq("regfrom", 3));
		log.info("共有{}个自然人", crowdsourceList.size());
		for (Crowdsource crowdsource : crowdsourceList) {
			CrowdsourceProjectItem item = new CrowdsourceProjectItem().selectOne(
					Condition.create().eq("crowdsourceid", crowdsource.getCrowdsourceid()).last("limit 1"));
			CrowdsourceAccount account = new CrowdsourceAccount().selectOne(
					Condition.create().eq("crowdsourceid", crowdsource.getCrowdsourceid()));
			if (item != null) {
				CrowdsourceProject project = new CrowdsourceProject().selectOne(Condition.create().eq("projectid", item.getProjectid()));
				if (project != null && account != null) {
					account.setBindcompid(project.getCompid()).updateById();
				}
			}
			crowdsource.setState(2).updateById();
		}
		log.info("结束fixCrowdsourceFromImprotProject ----- ");
	}

	public void fixImportCrowdsourceInvoice() {
		log.info("开始fixImportCrowdsourceInvoice -----");
		List<CrowdsourceProject> list = new CrowdsourceProject().selectList(Condition.create().eq("supplement", 1));
		log.info("共有{}个总包项目", list.size());
		for (CrowdsourceProject project : list) {
			List<CrowdsourceInvoice> invoiceList = new CrowdsourceInvoice().selectList(
					Condition.create().eq("projectid", project.getProjectid()));
			for (CrowdsourceInvoice invoice : invoiceList) {
				invoice.setCreatetime(project.getFinishtime()).setUpdatetime(project.getFinishtime()).updateById();
			}
		}
		log.info("结束fixImportCrowdsourceInvoice ----- ");
	}

	public void fixImportProjectInvoice() {
		log.info("开始 fixImportCrowdsourceProjectInvoice -----");
		List<CrowdsourceProject> list = new CrowdsourceProject().selectList(Condition.create().eq("supplement", 1));
		log.info("共有{}个众包项目", list.size());
		for (CrowdsourceProject project : list) {
			List<Invoice> invoiceList = new Invoice().selectList(
					Condition.create().eq("projectid", project.getProjectid()).eq("project_type", 2));
			for (Invoice invoice : invoiceList) {
				invoice.setCreatetime(project.getFinishtime()).setFinishtime(project.getFinishtime()).updateById();
			}
		}
		List<CompanyProject> cplist = new CompanyProject().selectList(Condition.create().eq("whether_supplement", 1));
		log.info("共有{}个 项目", cplist.size());
		for (CompanyProject companyProject : cplist) {
			List<Invoice> invoiceList = new Invoice().selectList(
					Condition.create().eq("projectid", companyProject.getProjectid()).eq("project_type", 1));
			for (Invoice invoice : invoiceList) {
				invoice.setCreatetime(companyProject.getProjectfinish()).setFinishtime(companyProject.getProjectfinish()).updateById();
			}
		}
		log.info("结束 fixImportCrowdsourceProjectInvoice ----- ");
	}

	public void fixEntrustProjectInvoice() {
		log.info("开始 fixEntrustProjectInvoice ----");
		List<EntrustmentProject> list = new EntrustmentProject().selectAll();
		for (EntrustmentProject project : list) {
			Integer projectType = project.getProjectType();
			Invoice invoice = new Invoice().selectOne(Condition.create().eq("projectid", project.getId()).eq("project_type", projectType));
			if (invoice != null) continue;
			List<EntrustmentProjectItem> itemList = new EntrustmentProjectItem().selectList(
					Condition.create().eq("import_id", project.getId()));
			if (NumberUtil.equals(projectType, ProjectType.ENTRUST_ZHIDUODUO)) {
				coreInvoiceService.createEntrustZhiduoduoProjectInvoice(itemList);
			} else if (NumberUtil.equals(projectType, ProjectType.ENTRUST_CROWDSOURCE)) {
				coreInvoiceService.createEntrustCrowdsourceProjectInvoice(itemList);
				CrowdsourceInvoice crowdsourceInvoice = new CrowdsourceInvoice().selectOne(
						Condition.create().eq("projectid", project.getId()).eq("project_type", projectType));
				if (crowdsourceInvoice == null) {
					coreInvoiceService.createEntrustCrowdsourceProjectMakerInvoice(itemList);
				}
			}
		}
		log.info("结束 fixEntrustProjectInvoice ----");
	}

	public void fixCreateZhiduoduoProjectInvoice(int projectid) {
		Invoice invoice = invoiceMapper.findByProjectid(projectid, ProjectType.ZHIDUODUO);
		Asserts.isNull(invoice, StatusMsg.StatusMsg_324);
		coreInvoiceService.createZhiduoduoProjectInvoice(projectid);
	}

	public void fixCrowdsourceInvoiceNewFields() {
		log.info("开始 fixCrowdsourceInvoiceNewFields ----");
		List<CrowdsourceInvoice> list = new CrowdsourceInvoice().selectAll();
		log.info("总数量:{}", list.size());
		for (CrowdsourceInvoice invoice : list) {
			try {
				String realName = "";
				Integer crowdsourceid = invoice.getCrowdsourceid();
				Integer userType = invoice.getUserType();
				if (NumberUtil.equals(userType, CrowdsourceUserType.NATURAL_PERSON)) {
					CrowdsourceAccount account = new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", crowdsourceid));
					realName = account != null ? account.getRealname() : "";
				} else if (NumberUtil.equals(userType, CrowdsourceUserType.STUDIO)) {
					MakerDetailDto userDetail = makerMapper.getUserDetail(crowdsourceid);
					realName = userDetail != null ? userDetail.getRealname() : "";
				}
				invoice.setRealName(realName);

				if (NumberUtil.equals(invoice.getProjectType(), ProjectType.CROWDSOURCE)) {
					CrowdsourceProject project = new CrowdsourceProject().selectById(invoice.getProjectid());
					if (project != null) {
						invoice.setProjectName(project.getProjectName());
						invoice.setInvoiceContent(project.getInvoiceContent());
						invoice.setCompid(project.getCompid());

						CompanyDetailDto companyInfo = companyMapper.getCompanyInfo(invoice.getCompid());
						if (companyInfo != null) {
							invoice.setCompname(companyInfo.getCompname());
							if (NumberUtil.safeInt(invoice.getPartyId()) == 0) {
								invoice.setPartyId(project.getPartyId());
							}
						}
					}
				}
				invoice.updateById();
			} catch (Exception e) {
				log.error("fixCrowdsourceInvoiceNewFields 报错", e);
			}
		}
		log.info("结束 fixCrowdsourceInvoiceNewFields ----");
	}

	public void fixNormalProjectBrokerage(int projectid) {
		CompanyProject project = new CompanyProject().selectById(projectid);
		Asserts.notNull(project);
		Company company = new Company().selectById(project.getCompid());
		// 先删除以前的佣金记录
		new PartnerBrokerage().delete(Condition.create().eq("projectid", projectid).eq("project_type", ProjectType.ZHIDUODUO));
		coreBrokerageService.prepareProjectBrokerage(company.getCompid(), project.getUserid(), project.getProjectid(),
				ProjectType.ZHIDUODUO);
		int tradeid = 0;
		String tradeno = "";
		TradeRecord tradeRecord = new TradeRecord().selectOne(Condition.create().eq("projectid", projectid).eq("repay", 0));
		if (tradeRecord != null) {
			tradeid = tradeRecord.getTradeid();
			tradeno = tradeRecord.getTradeno();
		}
		coreBrokerageService.handleZhiduoduoProjectPartnerBrokerage(project, tradeid, tradeno);
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	public int insertMaker() {
		Maker maker = new Maker();
		maker.setMakerType(1).setSex(1).insert();
		return maker.getUserid();
	}

	public void fixPartnerAccountFlow() {
		List<PartnerAccountflow> list = new PartnerAccountflow().selectList(Condition.create().eq("flowtype", 1));
		log.info("修复合伙人流水，总条数：{}", list.size());
		List<Integer> notMatchedList = Lists.newArrayList();
		for (PartnerAccountflow flow : list) {
			// 先通过交易id匹配
			Integer tradeid = flow.getTradeid();
			if (NumberUtil.safeInt(tradeid) > 0) {
				List<PartnerBrokerage> brokerageList = new PartnerBrokerage().selectList(Condition.create().eq("tradeid", tradeid));
				if (CollectionUtils.isNotEmpty(brokerageList)) {
					// 通过项目id匹配，满足交易id和项目id一致，则肯定是匹配的数据
					PartnerBrokerage partnerBrokerage = brokerageList.stream()
							.filter(b -> NumberUtil.equals(b.getProjectid(), flow.getProjectid()))
							.findAny()
							.orElse(null);
					if (partnerBrokerage != null) {
						flow.setCompid(partnerBrokerage.getCompid())
								.setUserid(partnerBrokerage.getUserid())
								.setBrokerageid(partnerBrokerage.getBrokerageid())
								.setProjectType(partnerBrokerage.getProjectType())
								.updateById();
						// 匹配成功，下一个
						continue;
					}
				}
			}
			// 交易id没有匹配上，直接用项目id去匹配，但是要处理多个相同的项目id的情况
			List<PartnerBrokerage> brokerageList = new PartnerBrokerage().selectList(
					Condition.create().eq("projectid", flow.getProjectid()));
			if (CollectionUtils.isNotEmpty(brokerageList)) {
				// 如果有多个项目id，则看流水记录时间与佣金更新时间最近的
				long flowTime = flow.getCreatetime().getTime();
				long delta = flowTime;
				PartnerBrokerage partnerBrokerage = brokerageList.get(0);
				for (PartnerBrokerage currBrokerage : brokerageList) {
					long time = currBrokerage.getUpdatetime().getTime();
					long currDelta = Math.abs(flowTime - time);
					if (currDelta < delta) {
						partnerBrokerage = currBrokerage;
						delta = currDelta;
					}
				}
				flow.setCompid(partnerBrokerage.getCompid())
						.setUserid(partnerBrokerage.getUserid())
						.setBrokerageid(partnerBrokerage.getBrokerageid())
						.setProjectType(partnerBrokerage.getProjectType())
						.updateById();
				continue;
			}
			// 还是没有匹配到
			notMatchedList.add(flow.getId());
		}
		log.info("没有匹配到的合伙人流水：{}", JSON.toJSONString(notMatchedList));
	}

	public void fixProjectUserNames() {
		log.info("fixProjectUserNames -- 开始");
		long start = System.currentTimeMillis();

		Map<Integer, MakerDetailDto> makerMap = Maps.newHashMap();
		Map<Integer, CrowdsourceAccount> crowdsourceMap = Maps.newHashMap();
		Map<Integer, Company> companyMap = Maps.newHashMap();
		log.info("fixProjectUserNames -- CompanyProject--》");
		new CompanyProject().selectAll().stream().parallel().forEach(cp -> {
			Company company = companyMap.computeIfAbsent(cp.getCompid(), cid -> new Company().selectById(cid));
			if (company != null) {
				cp.setCompname(company.getCompname());
			}
			MakerDetailDto maker = makerMap.computeIfAbsent(cp.getUserid(), uid -> makerMapper.getUserDetail(uid));
			if (maker != null) {
				cp.setUsername(maker.getUsername());
				cp.setRealname(maker.getRealname());
			}
			cp.updateById();
		});

		log.info("fixProjectUserNames -- CrowdsourceProject--》");
		new CrowdsourceProject().selectAll().parallelStream().forEach(cp -> {
			Company company = companyMap.computeIfAbsent(cp.getCompid(), cid -> new Company().selectById(cid));
			if (company != null) {
				cp.setCompname(company.getCompname());
			}
			cp.updateById();
		});
		new CrowdsourceProjectItem().selectAll().parallelStream().forEach(cpi -> {
			Integer userType = cpi.getUserType();
			if (NumberUtil.equals(userType, CrowdsourceUserType.STUDIO)) {
				MakerDetailDto maker = makerMap.computeIfAbsent(cpi.getUserid(), uid -> makerMapper.getUserDetail(uid));
				if (maker != null) {
					cpi.setUsername(maker.getUsername());
					cpi.setRealname(maker.getRealname());
				}
			} else {
				CrowdsourceAccount crowdsource = crowdsourceMap.computeIfAbsent(cpi.getUserid(),
						uid -> new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", uid)));
				if (crowdsource != null) {
					cpi.setUsername(crowdsource.getRealname()).setRealname(crowdsource.getRealname());
				}
			}
			cpi.updateById();
		});

		log.info("fixProjectUserNames -- EntrustmentProject--》");
		new EntrustmentProjectItem().selectAll().parallelStream().forEach(epi -> {
			Company company = companyMap.computeIfAbsent(epi.getCompid(), cid -> new Company().selectById(cid));
			if (company != null) {
				epi.setCompname(company.getCompname());
			}
			MakerDetailDto maker = makerMap.computeIfAbsent(epi.getEntrusteeId(), uid -> makerMapper.getUserDetail(uid));
			if (maker != null) {
				epi.setEntrusteeName(maker.getRealname());
				epi.setEntrusteeStudio(maker.getUsername());
			}
			CrowdsourceAccount crowdsource = crowdsourceMap.computeIfAbsent(epi.getCrowdsourceid(),
					uid -> new CrowdsourceAccount().selectById(uid));
			if (crowdsource != null) {
				epi.setCrowdsourceName(crowdsource.getRealname());
			}
			epi.updateById();
		});

		long end = System.currentTimeMillis();
		log.info("fixProjectUserNames -- 结束， 耗时：{} ms", end - start);
	}

	public void fixCrowdsourceItemName() {
		Map<Integer, MakerDetailDto> makerMap = Maps.newHashMap();
		Map<Integer, CrowdsourceAccount> crowdsourceMap = Maps.newHashMap();
		new CrowdsourceProjectItem().selectAll().parallelStream().forEach(cpi -> {
			Integer userType = cpi.getUserType();
			if (NumberUtil.equals(userType, CrowdsourceUserType.STUDIO)) {
				MakerDetailDto maker = makerMap.computeIfAbsent(cpi.getUserid(), uid -> makerMapper.getUserDetail(uid));
				if (maker != null) {
					cpi.setUsername(maker.getUsername());
					cpi.setRealname(maker.getRealname());
				}
			} else {
				CrowdsourceAccount crowdsource = crowdsourceMap.computeIfAbsent(cpi.getUserid(),
						uid -> new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", uid)));
				if (crowdsource != null) {
					cpi.setUsername(crowdsource.getRealname()).setRealname(crowdsource.getRealname());
				}
			}
			cpi.updateById();
		});
	}

	public SmartResult fixProjectInvoice(int projectid) {
		CompanyProject project = new CompanyProject().selectById(projectid);
		Asserts.notNull(project);
		// 创建发票
		Invoice invoice = companyProjectMapper.getPendingInvoiceDetail(project.getProjectid());
		if (invoice == null) return SmartResult.ofErrorParam();

		// 应付金额
		BigDecimal payAmount = project.getProjectservicecharge().add(project.getProjecttaxfee());
		String applyno = RandomUtil.createRandomNo("INVO_", "");
		invoice.setApplyno(applyno)
				.setUserid(project.getUserid())
				.setInvoiceAmount(project.getProjectdealamount())
				.setPayAmount(payAmount)
				.setState(Constants.invoicestate_2)
				.setProjectfinishtime(new Date());

		if (!invoice.insert()) throw SmartException.of("发票创建失败");
		return SmartResult.success();
	}

	public SmartResult fixCompanyNickname() {
		new Company().selectAll().parallelStream().forEach(company -> {
			if (NumberUtil.equals(company.getState(), Constants.comp_state_4) && StringUtil.isEmpty(company.getCompnickname())) {
				// 设置企业昵称
				String nickname = "zdd_" + MD5Util.md5(company.getCompname() + RandomUtil.generateString(8)).substring(0, 8).toLowerCase();
				company.setCompnickname(nickname).updateById();
			}
		});
		return SmartResult.success();
	}

	public SmartResult fixProjectCompanyNickname() {
		new CompanyProject().selectAll().parallelStream().forEach(project -> {
			if (StringUtil.isEmpty(project.getCompnickname())) {
				Company company = new Company().selectById(project.getCompid());
				if (company == null) return;
				// 设置企业昵称
				project.setCompnickname(company.getCompnickname()).updateById();
			}
		});
		return SmartResult.success();
	}

	public SmartResult generateZhaoshangSubLegderForCompany() {
		new Thread(() -> new CompanyAccount().selectAll().parallelStream().forEach(account -> {
			if (account.getRealnameAuth() != 2) return;
			if (!CompanyPayType.isZhaoShangPayType(account.getPayType())) return;

			Company company = new Company().selectById(account.getCompid());
			try {
				zhaoShangTradeBulterService.createSubLedgerIfNotExist(company, account.getPayType());
			} catch (Exception e) {
				log.error("批量新建企业招商银行记账子单元报错：企业id：{}", account.getCompid(), e);
			}

		})).start();
		return SmartResult.success();
	}

	public SmartResult repairCompany(){
		List<CompanyAccount> accounts = new CompanyAccount().selectAll();
		for (CompanyAccount account:accounts) {
			try {
				Company company = new Company().selectById(account.getCompid());
				if(company == null){
					log.error("企业数据未找到，修复失败：compid:" + account.getCompid());
					continue;
				}
				// 新建 支付方式
				CompanyParty zddParty = new CompanyParty();
				zddParty.setCompid(account.getCompid());
				zddParty.setPayId(account.getPayType());
				zddParty.setPartyId(company.getPartyId());
				zddParty.setIsDefault(1);
				zddParty.setBusinessSn("zdd");
				zddParty.insert();
				// 开启智众包的 新建智众包支付方式
				if(company.getIntelCrowdsource() == 2) {
					CompanyParty croParty = new CompanyParty();
					croParty.setCompid(account.getCompid());
					croParty.setPayId(account.getPayType());
					croParty.setPartyId(company.getPartyId());
					croParty.setCityId(company.getCrowdsourceCity());
					croParty.setIsDefault(1);
					croParty.setBusinessSn("cro");
					croParty.insert();
				}
				//开启智零工的
				if(company.getOpenOddJob() == 1){
					CompanyParty odd = new CompanyParty();
					odd.setCompid(account.getCompid());
					odd.setPayId(account.getPayType());
					odd.setPartyId(company.getPartyId());
					odd.setCityId(company.getCrowdsourceCity());
					odd.setTaxSourceId(account.getTaxSourceId());
					odd.setIsDefault(1);
					odd.setBusinessSn("odd");
					odd.insert();
				}

				if(account.getMakerGroupon() == 1) {
					if(account.getPrincipalId() != null && account.getPrincipalId() != 0){
						Payment groupPayment = new Payment().selectOne(Condition.create()
																				.eq("source_table",2)
																				.eq("pay_type_sn", PayTypeSn.ZFB_WTJD)
																				.eq("source_id",account.getPrincipalId()));
						if(groupPayment == null){
							log.error("企业创客团支付方式未找到，修复失败，企业id:{},企业名称:{}：,getPrincipalId{}", company.getCompid(),company.getCompname(), account.getPrincipalId());
							continue;
						}
						// 创建支付方式/创建余额
						CompanyParty group = new CompanyParty();
						group.setCompid(account.getCompid());
						group.setPayId(groupPayment.getId());
						group.setPartyId(company.getPartyId());
						group.setIsDefault(1);
						group.setBusinessSn("group");
						group.insert();

						CompanyPayment groupBalance = new CompanyPayment();
						groupBalance.setPayId(groupPayment.getId());
						groupBalance.setCompid(company.getCompid());
						groupBalance.setBalance(account.getMakerGrouponBalance());
						groupBalance.setFrozenBalance(account.getMakerGrouponFrozenBalance());
						groupBalance.insert();
					}
				}

				//同步创建企业余额

				CompanyPayment companyBalance = new CompanyPayment();
				companyBalance.setPayId(account.getPayType());
				companyBalance.setCompid(company.getCompid());
				companyBalance.setBalance(account.getBalance());
				companyBalance.setFrozenBalance(account.getFrozenBalance());
				companyBalance.insert();

			} catch (Exception e) {
				log.error("企业数据修复异常，请检查数据：compid:{},exception:{}", account.getCompid(), e);
			}
		}
		return SmartResult.success();
	}



}
